#include <iostream>
#include <boost/filesystem.hpp>
#include <ltdl.h>
#include <App.h>
#include <AppView.hpp>
#include <AppAction.hpp>
#include "AppLoader.h"

AppLoader::AppLoader(std::string folder) {
  boost::filesystem::path p(folder);
  if (boost::filesystem::exists(p)) {
    _folder = folder;
    lt_dlinit();
  } else {
    /* throw exception */
  }
}

AppLoader::~AppLoader() {
  if (_loaded.size() > 0) {
    for (unsigned int i = 0; i < _loaded.size(); i++) {
      unloadApp(_loaded[i]);
    }
  }
  lt_dlexit();
}

App* AppLoader::loadApp(std::string name) {
  // Linux name "libapp.so"
  std::string path(_folder + "/" + name + ".so");

  // Open file
  lt_dlhandle appCreator = lt_dlopen(path.c_str());

  if (!appCreator) {
    /* throw exception */
    std::cerr << "Cannot load application " << name << " " << lt_dlerror()
        << std::endl;
    return NULL;
  }

  lt_dlerror();

  // Load symbols
  create_appl* create_app = (create_appl*) lt_dlsym(appCreator, "create_application");
  
  const char* dlsym_error = lt_dlerror();
  if (dlsym_error) {
    /* throw exception */
    std::cerr << "Cannot load symbol create " << name << dlsym_error
        << std::endl;
    return NULL;
  }

  App* app = create_app();

  _loaded.push_back(app);

  return app;

}

void AppLoader::unloadApp(App* app) {
  delete app;
}
